#include <8052.h>
#include <compiler.h>
#include "lcd1602.h"
#include "DS18B20.h"
//https://blog.csdn.net/qq_41422043/article/details/89214676

/* 软件延时函数，延时时间(t*10)us */
void DS18B20_DelayX10us(unsigned char t)
{
    do
    {
        // 2x2 +  do-while 6个时钟周期 = 10 个时钟周期
        DS18B20_DELAY_2US;
        DS18B20_DELAY_2US;
    } while (--t);
}

/*长延时，大概500ms*/
void DS18B20_Delay_500ms() //@11.0592MHz
{
    unsigned char i, j;

    i = 255;
    j = 255;
    do
    {
        do
        {
        } while (--j);
    } while (--i);
}

/* 复位总线，获取存在脉冲，以启动一次读写操作 */
char DS18B20_Reset()
{
    char ack;
    DS18B20_DQ_OUT_L; //产生 500us 复位脉冲
    DS18B20_DelayX10us(50);
    DS18B20_DQ_OUT_H;
    DS18B20_DelayX10us(6); //延时 60us
    ack = IO_DS18B20;      //读取存在脉冲
    //char retry = 100;
    //while (!IO_DS18B20 || retry--)
    while (!IO_DS18B20)
    { //等待存在脉冲结束
        DS18B20_DELAY_2US;
    }
    //return > 0;
    return ack;
}

/* 向 DS18B20 写入一个字节，dat-待写入字节 */
void DS18B20_WriteByte(unsigned char data)
{
    for (char i = 0; i < 8; i++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT_L;
            DS18B20_DELAY_2US;
            DS18B20_DQ_OUT_H;
            DS18B20_DelayX10us(6); //延时 60us
        }
        else
        {
            DS18B20_DQ_OUT_L;
            DS18B20_DelayX10us(6); //延时 60us
            DS18B20_DQ_OUT_H;
            DS18B20_DELAY_2US;
        }
        data >>= 1;
    }
}

// 从传感器读取一个Bit数据
unsigned char DS18B20_Read_Bit(void)
{
    unsigned char data;
    DS18B20_DQ_OUT_L;
    DS18B20_DELAY_2US;
    DS18B20_DQ_OUT_H;
    DS18B20_DELAY_2US;
    data = IO_DS18B20;
    DS18B20_DelayX10us(6); //延时 60us
    return data;
}

// 从传感器中读取一个字节数据
unsigned char DS18B20_Read_Byte(void)
{
    unsigned char data = 0;
    for (char i = 0; i < 8; i++)
    {
        data >>= 1;
        if (DS18B20_Read_Bit())
        {
            data |= 0x80;
        }
    }
    return data;
}

/* 启动一次 18B20 温度转换，返回值-表示是否启动成功 */
char DS18B20_Start()
{
    char ack;
    ack = DS18B20_Reset(); //执行总线复位，并获取 18B20 应答
    if (ack == 0)
    {                            //如 18B20 正确应答，则启动一次转换
        DS18B20_WriteByte(0xCC); //跳过 ROM 操作
        DS18B20_WriteByte(0x44); //启动一次温度转换
    }
    return ~ack; //ack==0 表示操作成功，所以返回值对其取反
}

/* 读取 DS18B20 转换的温度值，返回值-表示是否读取成功 */
char DS18B20_GetTemp(int *temp)
{
    char ack;
    unsigned char LSB, MSB; //16bit 温度值的低字节和高字节
    ack = DS18B20_Reset();  //执行总线复位，并获取 18B20 应答
    if (ack == 0)
    {                                  //如 18B20 正确应答，则读取温度值
        DS18B20_WriteByte(0xCC);       //跳过 ROM 操作
        DS18B20_WriteByte(0xBE);       //发送读命令,读取暂存器中9字节数据
        LSB = DS18B20_Read_Byte();     //读温度值的低字节
        MSB = DS18B20_Read_Byte();     //读温度值的高字节
        *temp = ((int)MSB << 8) | LSB; //合成为 16bit 整型数

        //最终温度 = (((int)MSB << 8) | LSB) * 0.0625f;
    }
    return ~ack; //ack==0 表示操作应答，所以返回值为其取反值
}

void DS18B20_ShowTemp()
{
    int temp;
    char result;
    while (1)
    {

        DS18B20_Delay_500ms();
        result = DS18B20_Start(); //启动 DS18B20
        if (result)
        {
            DS18B20_Delay_500ms();
            result = DS18B20_GetTemp(&temp); //读取当前温度

            if (result)
            {
                //最后三位是小数
                long data = temp * 0.0625 * 1000;
                lcd1602_show_number(data);
            }
            // char HT = temp >> 8;
            // char LT = temp & 0xff;
        }
        //没有读取出来
        if (result == 0)
        {
            //P2_3为蜂鸣器
            P2_3 = 0;              //开启
            DS18B20_Delay_500ms(); //约为500ms
            DS18B20_Delay_500ms(); //约为500ms
            P2_3 = 1;              //关闭
        }
    }
}